package com.ease.core.components {
   import com.ease.core.events.DockingEvent;
   import com.ease.core.events.LayoutChangeEvent;
   import com.ease.core.layout.BorderLayout;
   import com.ease.core.managers.PerspectiveManager;
   import com.ease.util.KeyedSet;
   
   import flash.display.DisplayObject;
   
   import mx.containers.Canvas;
   import mx.core.UIComponent;
   import mx.effects.Move;
   import mx.effects.Parallel;
   import mx.effects.Resize;
   import mx.effects.easing.Exponential;

   public class StageView extends Canvas {
      private var parallel:Parallel;
      private var maximizeParallel:Parallel;

      public var items:KeyedSet = new KeyedSet(); // Stores the views which are not minimized.
      public var minimizedItems:KeyedSet = new KeyedSet(); // Stores the minimized views.
      public var maximizedWindow:ViewWindow;
      public var stageWindow:StageWindow;

      public function StageView() {
         super();
         addEventListener(DockingEvent.DOCKED, onDockingViewDock);
         addEventListener(DockingEvent.MAXIMIZE, onDockingViewMaximize);
         addEventListener(DockingEvent.MINIMIZE, onDockingViewMinimize);
         addEventListener(DockingEvent.REMOVED, onDockingViewRemoved);
         addEventListener(DockingEvent.RESTORE, onDockingViewRestore);
      }

      public function addView(view:DockingView, index:int = -1):void {
         var window:ViewWindow = null;
         if (maximizedWindow) {
            window = maximizedWindow;
         }
         else if (items.length == 0) {
            window = new ViewWindow();
            addChild(window);
            items.add(window);
         }
         else {
            window = getViewWindow(this);
         }

         if (!window.contains(view)) {
            if (index >= 0) {
               window.addChildAt(view, index);
            }
            else {
               window.addChild(view);
            }
         }
      }

      private function getViewWindow(parent:UIComponent):ViewWindow {
         var window:ViewWindow = null;
         var child:UIComponent = parent.getChildAt(0) as UIComponent;
         if (child is SplitWindow) {
            window = getViewWindow(child);
         }
         else if (child is ViewWindow) {
            window = child as ViewWindow;
         }
         return window;
      }

      protected function onDockingViewMinimize(event:DockingEvent):void {
         var viewWindow:ViewWindow = event.target as ViewWindow;
         minimizedItems.add(viewWindow);
         items.remove(viewWindow);

         updateLayout();
      }

      private function onDockingViewDock(event:DockingEvent):void {
         var viewTab:ViewTab = event.viewTab;
         var originalViewWindow:ViewWindow = viewTab.getViewWindow();
         var targetViewWindow:ViewWindow = event.viewWindow;
         var borderLayout:String = targetViewWindow.borderLayout;

         if (originalViewWindow != targetViewWindow || BorderLayout.CENTER != borderLayout) {
            var view:DockingView = originalViewWindow.removeChildAt(viewTab.parent.getChildIndex(viewTab)) as DockingView;
            insertView(view, borderLayout, targetViewWindow);
            updateLayout();
         }

         event.stopImmediatePropagation();
         event = null;
      }

      private function insertView(view:DockingView, borderLayout:String, targetViewWindow:ViewWindow):void {
         if (BorderLayout.CENTER == borderLayout) {
            targetViewWindow.addChild(view);
         }
         else {
            var newViewWindow:ViewWindow = new ViewWindow();
            newViewWindow.addChild(view);
            items.add(newViewWindow);

            var splitWindow:SplitWindow = new SplitWindow();
            splitWindow.percentWidth = targetViewWindow.percentWidth;
            splitWindow.percentHeight = targetViewWindow.percentHeight;

            splitWindow.direction = BorderLayout.toDirection(borderLayout);

            var parentComponent:UIComponent = targetViewWindow.parent as UIComponent;
            var splitWindowIndex:int = parentComponent.getChildIndex(targetViewWindow);
            parentComponent.removeChild(targetViewWindow);

            parentComponent.addChildAt(splitWindow, splitWindowIndex);

            if (true == splitWindow.isHorizontal()) {
               if (newViewWindow.originalWidth > 0) {
                  newViewWindow.width = (splitWindow.width > targetViewWindow.originalWidth) ? newViewWindow.originalWidth : splitWindow.width / 2;
                  newViewWindow.percentWidth = (targetViewWindow.width / splitWindow.width) * 100;

                  targetViewWindow.percentWidth = 100 - targetViewWindow.percentWidth;
               }
               else {
                  newViewWindow.percentWidth = targetViewWindow.percentWidth;
               }

               newViewWindow.percentHeight = targetViewWindow.percentHeight = 100;
            }
            else {
               if (newViewWindow.originalHeight > 0) {
                  newViewWindow.height = (splitWindow.height > targetViewWindow.originalHeight) ? newViewWindow.originalHeight : splitWindow.height / 2;
                  newViewWindow.percentHeight = (targetViewWindow.height / splitWindow.height) * 100;

                  targetViewWindow.percentHeight = 100 - targetViewWindow.percentHeight;
               }
               else {
                  newViewWindow.percentHeight = targetViewWindow.percentHeight;
               }
               newViewWindow.percentWidth = targetViewWindow.percentWidth = 100;
            }
            splitWindow.addChild(targetViewWindow);
            splitWindow.addChildAt(newViewWindow, BorderLayout.childIndex(borderLayout));
         }
      }

      private function onDockingViewMaximize(event:DockingEvent):void {

         var window:ViewWindow = ViewWindow(event.target);
         stageWindow.addChild(window);
         maximizeParallel = new Parallel();
         maximizeParallel.duration = 1000;
         addResizeAndMoveToParallel(window, maximizeParallel, stageWindow.width, stageWindow.height, 0, 0);
         maximizeParallel.play();

         maximizedWindow = window;

         items.remove(window);
         updateLayout();
      }

      private function onDockingViewRestore(event:DockingEvent):void {
         var window:ViewWindow = event.target as ViewWindow;
         items.add(window);
         if (window.windowState == ViewWindow.WINDOW_STATE_MAXIMIZED) {
            if (maximizeParallel != null && maximizeParallel.isPlaying)
               maximizeParallel.pause();

            maximizedWindow = null;
            maximizeParallel = new Parallel();
            maximizeParallel.play();
         }
         else {
            minimizedItems.remove(window);

            updateLayout();
         }
      }

      public function onDockingViewRemoved(event:DockingEvent):void {
         var targetView:DockingView = event.view;
         var targetViewWindow:ViewWindow = event.viewWindow;

         if (targetViewWindow.numChildren == 0) {
            items.remove(targetViewWindow);
            targetViewWindow.parent.removeChild(targetViewWindow);
         }
         updateLayout();
      }
      
      public function clear():void {
         removeAllChildren();
         items = new KeyedSet();
      }

      public function updateLayout():void {
         var len:Number = items.length;

         includeInLayout = visible = len > 0;
         var window:ViewWindow;

         if (parallel != null && parallel.isPlaying)
            parallel.pause();

         parallel = new Parallel();
         parallel.duration = 1000;

         len = minimizedItems.length;
         var minimizedViews:Array = minimizedItems.toArray();
         if (len > 0) {
            for (var ii:int = 0; ii < len; ii++) {
               window = ViewWindow(minimizedViews[ii]);
               addResizeAndMoveToParallel(window, parallel, 0, 0, 0, stageWindow.height);
            }
         }

         if (parallel != null && parallel.children.length > 0)
            parallel.play();

         PerspectiveManager.getInstance().dispatchEvent(new LayoutChangeEvent());
      }

      private function addResizeAndMoveToParallel(target:ViewWindow, parallel:Parallel, widthTo:Number, heightTo:Number, xTo:Number, yTo:Number):void {
         var resize:Resize = new Resize(target);
         resize.widthTo = widthTo;
         resize.heightTo = heightTo;
         resize.easingFunction = Exponential.easeOut;
         parallel.addChild(resize);

         var move:Move = new Move(target);
         move.xTo = xTo;
         move.yTo = yTo;
         move.easingFunction = Exponential.easeOut;
         parallel.addChild(move);
      }
   }
}